﻿namespace BattleCity.GameLogic

open System
open FMath
open UI
open Types
open Casanova
open GameState

//****************************************************************************************//
//                                  TANKS COLLISIONS                                       //
//****************************************************************************************//

module TanksCollisionsFunctions =
 
 let tankOutofMap(position : Vector2<m>) =
  let mutable intersection = false
  if mapBounding < position.X || mapBounding < position.Y then intersection <- true
  if -mapBounding > position.X || -mapBounding > position.Y then intersection <- true
  intersection

 (*---------------------------------------------------------------------------
    Prende in ingresso lo stato di un carro nemico e verifica se è stato 
    colpito da un proiettile (ovvero è incluso nella hittedEnemiesList).
    
    Restituisce un booleano: 
    true -> colpito
    false -> non colpito                                                                 
  ---------------------------------------------------------------------------*)

 let isTankHitted (tankIndex : ref<int>) =
  let lenght = gameState.HittedEnemiesList.Value.Length
  let mutable i = 0
  let mutable hitted = false
  while i < lenght do
   if tankIndex.Value = gameState.HittedEnemiesList.Value.[i] then 
    hitted <- true
    i <- lenght + 1
   i <- i + 1
  hitted

 (*---------------------------------------------------------------------------
    Prende in ingresso lo stato di un carro nemico e verifica se collide con
    uno degli altri carri presenti sulla mappa.
    
    Restituisce un booleano: 
    true -> collide
    false -> non collide                                                             
  ---------------------------------------------------------------------------*)

 let ETankToTanksCollision (collisionSquare: Square, direction: Vector2<1>, listPosition : int) =
  let mutable collision = false
  let mutable i = 0
  let mutable intersectionOne = (0.0, 0.0)
  let mutable intersectionTwo = (0.0, 0.0)
  let lenght = (!gameState.EnemiesList).Length

  //cerco la collisione di un carro nemico con un altro carro nemico
  while i < lenght  && collision = false do
   let oneTank = (!gameState.EnemiesList).[i]
   if i <> listPosition then
       if (direction == Vector2<1>.Down) ||  (direction == Vector2<1>.Up) then 
            intersectionOne <- collisionSquare.Intersect((!oneTank).CollisionSquare, Side.Top)
            intersectionTwo <- collisionSquare.Intersect((!oneTank).CollisionSquare, Side.Bottom)
     
       elif (direction == Vector2<1>.Left) ||  (direction == Vector2<1>.Right) then
            intersectionOne <- collisionSquare.Intersect((!oneTank).CollisionSquare, Side.Right)
            intersectionTwo <- collisionSquare.Intersect((!oneTank).CollisionSquare, Side.Left)
       
       if intersectionOne <> (0.0,0.0) || intersectionTwo <> (0.0,0.0) then
            collision <- true
   i <- i + 1
 
  //cerco la collisione di un carro nemico con il carro del giocatore
   if (direction == Vector2<1>.Down) ||  (direction == Vector2<1>.Up) then 
        intersectionOne <- collisionSquare.Intersect((!gameState.PlayerTank).CollisionSquare, Side.Top)
        intersectionTwo <- collisionSquare.Intersect((!gameState.PlayerTank).CollisionSquare, Side.Bottom)
     
   elif (direction == Vector2<1>.Left) ||  (direction == Vector2<1>.Right) then
        intersectionOne <- collisionSquare.Intersect((!gameState.PlayerTank).CollisionSquare, Side.Right)
        intersectionTwo <- collisionSquare.Intersect((!gameState.PlayerTank).CollisionSquare, Side.Left)
       
   if intersectionOne <> (0.0,0.0) || intersectionTwo <> (0.0,0.0) then
        collision <- true

  collision

 (*---------------------------------------------------------------------------
    Prende in ingresso lo stato del carro giocatore e verifica se collide
    con uno dei carri nemici.
    
    Restituisce un booleano: 
    true -> collide
    false -> non collide                                                             
  ---------------------------------------------------------------------------*)
 let PlayerTankToETanksCollision (collisionSquare: Square, direction: Vector2<1>) =
  let mutable collision = false
  let mutable i = 0
  let mutable intersectionOne = (0.0, 0.0)
  let mutable intersectionTwo = (0.0, 0.0)
  let lenght = (!gameState.EnemiesList).Length

  //cerco la collisione del giocatore con un altro carro nemico
  while i < lenght  && collision = false do
    let oneTank = (!gameState.EnemiesList).[i]
    if (direction == Vector2<1>.Down) ||  (direction == Vector2<1>.Up) then 
        intersectionOne <- collisionSquare.Intersect((!oneTank).CollisionSquare, Side.Top)
        intersectionTwo <- collisionSquare.Intersect((!oneTank).CollisionSquare, Side.Bottom)
    elif (direction == Vector2<1>.Left) ||  (direction == Vector2<1>.Right) then
        intersectionOne <- collisionSquare.Intersect((!oneTank).CollisionSquare, Side.Right)
        intersectionTwo <- collisionSquare.Intersect((!oneTank).CollisionSquare, Side.Left)
    if intersectionOne <> (0.0,0.0) || intersectionTwo <> (0.0,0.0) then
        collision <- true
    i <- i + 1

  collision

 //---------------------------------------------------------------------------//
 // Prende in ingresso lo stato di uno dei carri e verifica se collide        //
 // con uno dei blocchi della mappa.                                          //
 //---------------------------------------------------------------------------//
 let rec checkTankBlocksCollision (collisionSquare : Square, direction : Vector2<1>) =   
  let mutable collision = false;
  let mutable stealth = false;
  let mutable turnBackCollision = false
  let mutable i,j = 0,0
  let mutable intersectionOne = (0.0, 0.0)
  let mutable intersectionTwo = (0.0, 0.0)
  while i <= blockMapSize && collision = false do
   j <- 0
   while j <= blockMapSize && collision = false do
    match gameState.BlockGrid.[i,j].makeUp with

     | CeramicBrick(brickArray) -> if (direction == Vector2<1>.Down) ||  (direction == Vector2<1>.Up) then 
                                        intersectionOne <- gameState.BlockGrid.[i,j].collisionSquare.Value.Intersect(collisionSquare, Side.Top)
                                        intersectionTwo <- gameState.BlockGrid.[i,j].collisionSquare.Value.Intersect(collisionSquare, Side.Bottom)
     
                                   elif (direction == Vector2<1>.Left) ||  (direction == Vector2<1>.Right) then
                                        intersectionOne <- gameState.BlockGrid.[i,j].collisionSquare.Value.Intersect(collisionSquare, Side.Right)
                                        intersectionTwo <- gameState.BlockGrid.[i,j].collisionSquare.Value.Intersect(collisionSquare, Side.Left)
       
                                   if intersectionOne <> (0.0,0.0) || intersectionTwo <> (0.0,0.0) then
                                        collision <- checkTankBricksCollision(collisionSquare, gameState.BlockGrid.[i,j].position, !brickArray, 4)

     | SteelBrick(brickArray)  ->  if (direction == Vector2<1>.Down) ||  (direction == Vector2<1>.Up) then 
                                        intersectionOne <- gameState.BlockGrid.[i,j].collisionSquare.Value.Intersect(collisionSquare, Side.Top)
                                        intersectionTwo <- gameState.BlockGrid.[i,j].collisionSquare.Value.Intersect(collisionSquare, Side.Bottom)
                                   else
                                        intersectionOne <- gameState.BlockGrid.[i,j].collisionSquare.Value.Intersect(collisionSquare, Side.Right)
                                        intersectionTwo <- gameState.BlockGrid.[i,j].collisionSquare.Value.Intersect(collisionSquare, Side.Left)

                                   if intersectionOne <> (0.0,0.0) || intersectionTwo <> (0.0,0.0) then
                                        turnBackCollision <- true
                                        collision <- checkTankSteelCollision(collisionSquare, gameState.BlockGrid.[i,j].position, !brickArray, 2)

     | Space ->                    if (direction == Vector2<1>.Down) ||  (direction == Vector2<1>.Up) then 
                                        intersectionOne <- gameState.BlockGrid.[i,j].collisionSquare.Value.Intersect(collisionSquare, Side.Top)
                                        intersectionTwo <- gameState.BlockGrid.[i,j].collisionSquare.Value.Intersect(collisionSquare, Side.Bottom)
     
                                   else
                                        intersectionOne <- gameState.BlockGrid.[i,j].collisionSquare.Value.Intersect(collisionSquare, Side.Right)
                                        intersectionTwo <- gameState.BlockGrid.[i,j].collisionSquare.Value.Intersect(collisionSquare, Side.Left)

                                   if intersectionOne <> (0.0,0.0) || intersectionTwo <> (0.0,0.0) then
                                    turnBackCollision <- true
                                    collision <- true

     | Stealth ->                  if (direction == Vector2<1>.Down) ||  (direction == Vector2<1>.Up) then 
                                        intersectionOne <- gameState.BlockGrid.[i,j].collisionSquare.Value.Intersect(collisionSquare, Side.Top)
                                        intersectionTwo <- gameState.BlockGrid.[i,j].collisionSquare.Value.Intersect(collisionSquare, Side.Bottom)
     
                                   else
                                        intersectionOne <- gameState.BlockGrid.[i,j].collisionSquare.Value.Intersect(collisionSquare, Side.Right)
                                        intersectionTwo <- gameState.BlockGrid.[i,j].collisionSquare.Value.Intersect(collisionSquare, Side.Left)

                                   if intersectionOne <> (0.0,0.0) || intersectionTwo <> (0.0,0.0) then stealth <- true
                    
     | _ -> ()
   
    j <- j + 1
   i <- i + 1

  (collision , stealth, turnBackCollision )
  
 and checkTankBricksCollision (collisionSquare : Square, blockPosition : Vector2<m>, brickArray : bool[,], brickCount : int) =
  let brickSize = blockSize / 4.0
  let mutable collision = false
  let mutable i,j = 0,0
  while i < brickCount && collision = false do
   j <- 0
   while j < brickCount && collision = false do
    if(brickArray.[i,j]) then
     let brickXposOffset = (float)((j + 1) - 2) * brickSize - (brickSize * 0.5)
     let brickYposOffset = (float)((i + 1) - 2) * brickSize - (brickSize * 0.5)
     let brickPosition = Vector2(blockPosition.X + brickXposOffset, blockPosition.Y + brickYposOffset)
     let brickCollisionSquare = Square(brickPosition, brickSize) 
     if brickCollisionSquare.Intersect(collisionSquare, Side.Bottom) <> (0.0,0.0) then
      collision <- true
    j <- j + 1
   i <- i + 1
  collision

 and checkTankSteelCollision (collisionSquare : Square, blockPosition : Vector2<m>, brickArray : bool[,], brickCount : int) =
  let brickSize = blockSize / 2.0
  let mutable collision = false
  let mutable i,j = 0,0
  while i < brickCount && collision = false do
   j <- 0
   while j < brickCount && collision = false do
    if(brickArray.[i,j]) then
     let brickXposOffset = (float)(j - 1) * brickSize + (brickSize * 0.5)
     let brickYposOffset = (float)(i - 1) * brickSize + (brickSize * 0.5)
     let brickPosition = Vector2(blockPosition.X + brickXposOffset, blockPosition.Y + brickYposOffset)
     let brickCollisionSquare = Square(brickPosition, brickSize) 
     if brickCollisionSquare.Intersect(collisionSquare, Side.Bottom) <> (0.0,0.0) then
      collision <- true
    j <- j + 1
   i <- i + 1
  collision

